# -*- coding: utf-8 -*-
# Author   : ZhangQing
# Time     : 2025-08-04 23:26
# File     : code_editor.py
# Project  : codebuddy_craft
# Desc     :
# frontend/components/code_editor.py
import streamlit as st
from streamlit_ace import st_ace
import asyncio
from typing import Dict, Any, Optional


class CodeEditor:
    """代码编辑器组件"""
    
    def __init__(self, api_client, state_manager):
        self.api_client = api_client
        self.state_manager = state_manager
    
    def render(self, file_info: Dict[str, Any]) -> str:
        """渲染代码编辑器"""
        
        # 获取文件内容
        if file_info['id'] not in st.session_state:
            content = asyncio.run(self._load_file_content(file_info['id']))
            st.session_state[file_info['id']] = content
        
        current_content = st.session_state[file_info['id']]
        
        # 确定编程语言
        language = self._detect_language(file_info['name'])
        
        # 编辑器配置
        editor_options = {
            'enableBasicAutocompletion': True,
            'enableLiveAutocompletion': True,
            'enableSnippets': True,
            'showLineNumbers': True,
            'showPrintMargin': True,
            'showGutter': True,
            'highlightActiveLine': True,
            'wrap': False,
            'fontSize': 14
        }
        
        # 渲染ACE编辑器
        edited_content = st_ace(
            value=current_content,
            language=language,
            theme='monokai',
            key=f"editor_{file_info['id']}",
            height=500,
            auto_update=False,
            font_size=14,
            tab_size=4,
            wrap=False,
            annotations=None,
            markers=None,
            **editor_options
        )
        
        # 更新会话状态
        if edited_content != current_content:
            st.session_state[file_info['id']] = edited_content
            st.session_state[f"{file_info['id']}_modified"] = True
        
        # 显示修改状态
        if st.session_state.get(f"{file_info['id']}_modified", False):
            st.warning("⚠️ 文件已修改，记得保存！")
        
        # 编辑器工具栏
        self._render_editor_toolbar(file_info, edited_content, language)
        
        return edited_content
    
    def _render_editor_toolbar(self, file_info: Dict[str, Any], content: str, language: str):
        """渲染编辑器工具栏"""
        
        col1, col2, col3, col4 = st.columns(4)
        
        with col1:
            if st.button("🔍 语法检查", key=f"syntax_check_{file_info['id']}"):
                self._check_syntax(content, language, file_info['id'])
        
        with col2:
            if st.button("📝 生成注释", key=f"generate_comment_{file_info['id']}"):
                self._generate_comment(content, language, file_info['id'])
        
        with col3:
            if st.button("🔄 翻译代码", key=f"translate_code_{file_info['id']}"):
                self._show_translation_dialog(content, language)
        
        with col4:
            # 显示文件统计信息
            lines = len(content.split('\n'))
            chars = len(content)
            st.caption(f"📊 {lines} 行, {chars} 字符")
    
    def _check_syntax(self, content: str, language: str, file_id: str):
        """检查语法"""
        try:
            result = asyncio.run(
                self.api_client.check_syntax(content, language)
            )
            
            if result['data']['errors']:
                with st.expander("❌ 发现语法错误", expanded=True):
                    for error in result['data']['errors']:
                        st.error(f"第 {error['line']} 行: {error['message']}")
                        if error.get('suggestion'):
                            st.info(f"💡 建议: {error['suggestion']}")
            else:
                st.success("✅ 语法检查通过！")
        
        except Exception as e:
            st.error(f"语法检查失败: {str(e)}")
    
    def _generate_comment(self, content: str, language: str, file_id: str):
        """生成注释"""
        try:
            result = asyncio.run(
                self.api_client.generate_comment(content, language)
            )
            
            comment = result['data']['comment']
            
            with st.expander("📝 生成的注释", expanded=True):
                st.code(comment, language=language)
                
                if st.button("插入注释", key=f"insert_comment_{file_id}"):
                    # 将注释插入到代码开头
                    new_content = f"{comment}\n\n{content}"
                    st.session_state[file_id] = new_content
                    st.success("注释已插入！")
                    st.experimental_rerun()
        
        except Exception as e:
            st.error(f"注释生成失败: {str(e)}")
    
    def _show_translation_dialog(self, content: str, source_language: str):
        """显示代码翻译对话框"""
        
        with st.expander("🔄 代码翻译", expanded=True):
            target_languages = [
                "Python", "JavaScript", "Java", "C++", "Go", 
                "Rust", "TypeScript", "C#", "PHP", "Ruby"
            ]
            
            target_language = st.selectbox(
                "选择目标语言:",
                target_languages,
                key="translation_target"
            )
            
            if st.button("开始翻译", key="start_translation"):
                try:
                    result = asyncio.run(
                        self.api_client.translate_code(
                            content, source_language, target_language
                        )
                    )
                    
                    translated_code = result['data']['translated_code']
                    
                    st.success("翻译完成！")
                    st.code(translated_code, language=target_language.lower())
                    
                    if st.button("复制翻译结果", key="copy_translation"):
                        st.success("翻译结果已复制到剪贴板！")
                
                except Exception as e:
                    st.error(f"代码翻译失败: {str(e)}")
    
    def _detect_language(self, filename: str) -> str:
        """根据文件名检测编程语言"""
        
        extension_map = {
            '.py': 'python',
            '.js': 'javascript',
            '.ts': 'typescript',
            '.jsx': 'jsx',
            '.tsx': 'tsx',
            '.java': 'java',
            '.cpp': 'c_cpp',
            '.c': 'c_cpp',
            '.h': 'c_cpp',
            '.hpp': 'c_cpp',
            '.cs': 'csharp',
            '.php': 'php',
            '.rb': 'ruby',
            '.go': 'golang',
            '.rs': 'rust',
            '.html': 'html',
            '.css': 'css',
            '.scss': 'scss',
            '.json': 'json',
            '.xml': 'xml',
            '.yaml': 'yaml',
            '.yml': 'yaml',
            '.md': 'markdown',
            '.sql': 'sql',
            '.sh': 'sh',
            '.txt': 'text'
        }
        
        for ext, lang in extension_map.items():
            if filename.lower().endswith(ext):
                return lang
        
        return 'text'
    
    async def _load_file_content(self, file_id: str) -> str:
        """加载文件内容"""
        try:
            result = await self.api_client.get_file_content(file_id)
            return result['data']['content']
        except Exception as e:
            st.error(f"加载文件失败: {str(e)}")
            return ""
    
    async def save_file(self, file_id: str, content: str) -> bool:
        """保存文件"""
        try:
            result = await self.api_client.save_file(file_id, content)
            
            if result['code'] == 200:
                # 清除修改标记
                st.session_state[f"{file_id}_modified"] = False
                return True
            else:
                return False
        
        except Exception as e:
            st.error(f"保存文件失败: {str(e)}")
            return False
    
    async def format_code(self, content: str, language: str) -> Optional[str]:
        """格式化代码"""
        try:
            result = await self.api_client.format_code(content, language)
            
            if result['code'] == 200:
                return result['data']['formatted_code']
            else:
                return None
        
        except Exception as e:
            st.error(f"代码格式化失败: {str(e)}")
            return None

